package com.mingqijia.gassafety.authority.dal.provider;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mingqijia.gassafety.authority.dal.command.CreatePrivilegeCommand;
import com.mingqijia.gassafety.authority.dal.command.QueryPrivilegeCommand;
import com.mingqijia.gassafety.authority.dal.command.RemovePrivilegeCommand;
import com.mingqijia.gassafety.authority.dal.command.UpdatePrivilegeCommand;
import com.mingqijia.gassafety.authority.dal.handler.PrivilegeTranslator;
import com.mingqijia.gassafety.db.entity.auth.PrivilegeEntry;
import com.mingqijia.gassafety.db.mapper.auth.PrivilegeMapper;
import com.mingqijia.gassafety.shared.constant.Constants;
import com.mingqijia.gassafety.shared.cqrs.QueryHandler;
import com.mingqijia.gassafety.shared.enums.RunningState;
import com.mingqijia.gassafety.shared.enums.SubjectType;
import com.mingqijia.gassafety.shared.enums.YesNoEnum;
import com.mingqijia.gassafety.shared.handler.GlobalAuthenticationException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * 信息CU操作(C-create,U-update)
 * @author Damon S.
 * @version v0.2
 * @date 2021-06-19
 */
@Slf4j
@Component
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class PrivilegeProvider extends ServiceImpl<PrivilegeMapper, PrivilegeEntry> implements QueryHandler<PrivilegeEntry> {

    private final PrivilegeTranslator translator;


    public List<PrivilegeEntry> find(List<String> privileges) {
        return this.listByIds(privileges);
    }

    public List<PrivilegeEntry> findByRoleIds(List<String> roleIds) {
        if (CollectionUtils.isEmpty(roleIds)) {
            throw new GlobalAuthenticationException("无效的用户角色");
        }
        QueryWrapper<PrivilegeEntry> queryClause = new QueryWrapper<>();
        queryClause.lambda().in(PrivilegeEntry::getSubjectId, roleIds)
                .eq(PrivilegeEntry::getSubjectType, SubjectType.ROLE.getCode())
                .eq(PrivilegeEntry::getIsDeleted, YesNoEnum.N.getCode())
                .eq(PrivilegeEntry::getState, RunningState.RUNNING.getCode());

        return this.list(queryClause);
    }

    public Page<PrivilegeEntry> find(QueryPrivilegeCommand command) {
        LambdaQueryWrapper<PrivilegeEntry> queryClause = new LambdaQueryWrapper<>();
        Optional.ofNullable(command.getSubjectId()).ifPresent(
                subId -> queryClause.eq(PrivilegeEntry::getSubjectId, subId)
        );
        Optional.ofNullable(command.getSubjectType()).ifPresent(
                subType -> queryClause.eq(PrivilegeEntry::getSubjectType, subType.getCode())
        );
        Optional.ofNullable(command.getSpId()).ifPresent(
                spId -> queryClause.eq(PrivilegeEntry::getSpId, spId)
        );
        Optional.ofNullable(command.getPrivilegeType()).ifPresent(
                privType -> queryClause.eq(PrivilegeEntry::getPrivilegeType, privType.getCode())
        );
        if (Objects.nonNull(command.getState()) && !RunningState.NA.equals(command.getState())) {
            queryClause.eq(PrivilegeEntry::getState, command.getState().getCode());
        }
        queryClause.eq(PrivilegeEntry::getIsDeleted, YesNoEnum.N.getCode());
        return this.page(createPage(command), queryClause);
    }

    public String create(CreatePrivilegeCommand command) {
        this.attachOperator2Command(command);

        if (Objects.isNull(command.getState()) || RunningState.NA.equals(command.getState())) {
            command.setState(RunningState.RUNNING);
        }
        if (ObjectUtils.isEmpty(command.getSubjectType())) {
            command.setSubjectType(SubjectType.ROLE);
        }

        if (SubjectType.NA.equals(command.getSubjectType())) {
            throw new GlobalAuthenticationException("权限主体[SubjectType]类型不合法");
        }
        QueryWrapper<PrivilegeEntry> queryClause = new QueryWrapper<>();
        queryClause.lambda().eq(PrivilegeEntry::getSubjectId, command.getSubjectId())
                .eq(PrivilegeEntry::getSubjectType, command.getSubjectType().getCode());

        if (!Objects.equals(Constants.INT_ZERO, this.count(queryClause))) {
            throw new GlobalAuthenticationException("权限已存在");
        }
        PrivilegeEntry entry = translator.toEntry(command);
        if (!this.save(entry)) {
            throw new GlobalAuthenticationException("添加权限失败");
        }
        return entry.getId();
    }

    public boolean update(UpdatePrivilegeCommand command) {
        this.attachOperator2Command(command);

        LambdaUpdateWrapper<PrivilegeEntry> updateClause = new LambdaUpdateWrapper<>();
        updateClause.eq(PrivilegeEntry::getId, command.getPrivId())
                .set(PrivilegeEntry::getData, command.getData())
                .set(PrivilegeEntry::getUpdatedBy, command.getUpdatedBy());

        return this.update(updateClause);
    }

    public boolean remove(RemovePrivilegeCommand command) {
        this.attachOperator2Command(command);

        LambdaUpdateWrapper<PrivilegeEntry> updateClause = new LambdaUpdateWrapper<>();
        updateClause.eq(PrivilegeEntry::getId, command.getPrivId())
                .set(PrivilegeEntry::getIsDeleted, YesNoEnum.Y.getCode())
                .set(PrivilegeEntry::getUpdatedBy, command.getUpdatedBy());

        return this.update(updateClause);
    }
}
